home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / MacPerl 5.1.3 / Mac_Perl_513_src / MacPerl5 / MPEditor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-20  |  14.8 KB  |  652 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl                -    Real Perl Application
  3. File        :    MPEditor.c            -    Delegate to external editor
  4. Author    :    Matthias Neeracher
  5.  
  6. Language    :    MPW C
  7.  
  8. $Log: MPGlobals.h,v $
  9. *********************************************************************/
  10.  
  11. #include "MPGlobals.h"
  12. #include "MPEditor.h"
  13. #include "SubLaunch.h"
  14. #include "MPWindow.h"
  15. #include "MPScript.h"
  16. #include "MPSave.h"
  17. #include "MPFile.h"
  18. #include "MPUtils.h"
  19.  
  20. #include <AEBuild.h>
  21. #include <AppleEvents.h>
  22. #include <AERegistry.h>
  23. #include <Files.h>
  24. #include <Folders.h>
  25. #include <StandardFile.h>
  26. #include <string.h>
  27. #include <Lists.h>
  28.  
  29. #define FAILOSERR(call) if (err = call) return err; else 0
  30.  
  31. static short        gExternalFileCount = 0;
  32. static FSSpec **    gExternalFiles         = nil;
  33.  
  34. static OSErr EditorRunning(OSType creator, ProcessSerialNumber *psn)
  35. {
  36.     OSErr err;
  37.     ProcessInfoRec info;
  38.     
  39.     psn->highLongOfPSN = 0;
  40.     psn->lowLongOfPSN  = kNoProcess;
  41.     do    {
  42.         FAILOSERR(GetNextProcess(psn));
  43.             
  44.         info.processInfoLength     = sizeof(info);
  45.         info.processName             = nil;
  46.         info.processAppSpec         = nil;
  47.         
  48.         FAILOSERR(GetProcessInformation(psn, &info));
  49.     } while(info.processSignature != creator);
  50.  
  51.     *psn = info.processNumber;
  52.     
  53.     return noErr;
  54. }
  55.  
  56. static OSErr GetSysVolume(short *vRefNum)
  57. {
  58.     long dir;
  59.     
  60.     return FindFolder(kOnSystemDisk, kSystemFolderType, false, vRefNum, &dir);
  61. }
  62.  
  63. static OSErr GetIndVolume(short index, short *vRefNum)
  64. {
  65.     OSErr             err;
  66.     ParamBlockRec     pb;
  67.     
  68.     pb.volumeParam.ioNamePtr     = nil;
  69.     pb.volumeParam.ioVolIndex     = index;
  70.     
  71.     FAILOSERR(PBGetVInfoSync(&pb));
  72.     
  73.     *vRefNum = pb.volumeParam.ioVRefNum;
  74.     
  75.     return noErr;
  76. }
  77.  
  78. static OSErr VolHasDesktopDB(short vRefNum, Boolean * hasDesktop)
  79. {
  80.     OSErr                         err;
  81.     HParamBlockRec             pb;
  82.     GetVolParmsInfoBuffer     info;
  83.     
  84.     pb.ioParam.ioNamePtr     = nil;
  85.     pb.ioParam.ioVRefNum     = vRefNum;
  86.     pb.ioParam.ioBuffer         = (Ptr)&info;
  87.     pb.ioParam.ioReqCount     = sizeof(GetVolParmsInfoBuffer);
  88.     
  89.     FAILOSERR(PBHGetVolParmsSync(&pb));
  90.  
  91.     *hasDesktop = (info.vMAttrib & (1 << bHasDesktopMgr))!=0;
  92.     
  93.     return noErr;
  94. }
  95.  
  96. static OSErr FindAppOnVolume(OSType signature, short vRefNum, FSSpec *file)
  97. {
  98.     OSErr     err;
  99.     DTPBRec     pb;
  100.     
  101.     /* Get Acess path to Desktop database on this volume */
  102.     
  103.     pb.ioVRefNum         = vRefNum;
  104.     pb.ioNamePtr         = nil;
  105.     FAILOSERR(PBDTGetPath(&pb));
  106.     
  107.     pb.ioIndex             = 0;
  108.     pb.ioFileCreator     = signature;
  109.     pb.ioNamePtr         = file->name;
  110.     switch (err = PBDTGetAPPLSync(&pb))    {
  111.     case noErr:
  112.         file->vRefNum     = vRefNum;
  113.         file->parID     = pb.ioAPPLParID;
  114.     
  115.         return noErr;
  116.     case fnfErr:
  117.         return afpItemNotFound;                        /* Bug in PBDTGetAPPL            */
  118.     default:
  119.         return err;
  120.     }
  121. }
  122.  
  123. static OSErr LaunchIt(FSSpecPtr fileSpec, ProcessSerialNumber * psn )
  124. {
  125.     OSErr                     err;
  126.     LaunchParamBlockRec     pb;
  127.     
  128.     pb.launchBlockID             = extendedBlock;
  129.     pb.launchEPBLength         = extendedBlockLen;
  130.     pb.launchFileFlags         = launchNoFileFlags;
  131.     pb.launchControlFlags    = launchContinue + launchNoFileFlags;
  132.     pb.launchAppSpec             = fileSpec;
  133.     pb.launchAppParameters    = nil;
  134.     
  135.     FAILOSERR(LaunchApplication(&pb));
  136.  
  137.     *psn = pb.launchProcessSN;
  138.     
  139.     return noErr;
  140. }
  141.  
  142. static OSErr FindExternalEditor(OSType signature, FSSpec *spec)
  143. {
  144.     OSErr     err;
  145.     short     vRefNum, sysVRefNum, index;
  146.     Boolean     hasDesktopDB;
  147.     
  148.     FAILOSERR(GetSysVolume(&sysVRefNum));
  149.     
  150.     vRefNum = sysVRefNum;
  151.     
  152.     for (index = 0; !err; err = GetIndVolume(++index,&vRefNum)) {
  153.         if (!index || vRefNum != sysVRefNum) {
  154.             if (err = VolHasDesktopDB(vRefNum,&hasDesktopDB))
  155.                 return err;
  156.                 
  157.             if (hasDesktopDB)    
  158.                 switch (err = FindAppOnVolume(signature, vRefNum, spec))    {
  159.                 case noErr:
  160.                     return noErr;
  161.                 case afpItemNotFound:
  162.                     break;
  163.                 default:
  164.                     return err;
  165.                 }
  166.         }
  167.     }
  168.     
  169.     return fnfErr;
  170. }
  171.  
  172. #define CLEANUPOSERR(e)    if (err = e) goto cleanup; else 0
  173.  
  174. OSErr FindHelper(StringPtr helperName, ICAppSpecHandle * helperHdl, Boolean launch)
  175. {
  176.     OSErr                        err = fnfErr;
  177.     ICAttr                    attr;
  178.     long                        size = sizeof(ICFileSpec);
  179.     FSSpec                    spec;
  180.     ICAppSpecHandle        helperPref;
  181.     ProcessSerialNumber    psn;
  182.     
  183.     if (gICInstance && 
  184.         !ICGetPrefHandle(gICInstance, helperName, &attr, (Handle *)&helperPref)
  185.     ) {
  186.         if (!launch || (err = EditorRunning(helperPref[0]->fCreator, &psn))) {
  187.             CLEANUPOSERR(FindExternalEditor(helperPref[0]->fCreator, &spec));
  188.             HLock((Handle) helperPref);
  189.             memcpy(helperPref[0]->name, spec.name, *spec.name+1);
  190.             HUnlock((Handle) helperPref);
  191.             if (launch)
  192.                 CLEANUPOSERR(LaunchIt(&spec, &psn));
  193.         }
  194.     } else
  195.         helperPref = nil;
  196.         
  197. cleanup:
  198.     if (!err && helperHdl)
  199.         *helperHdl = helperPref;
  200.     else if (helperPref)
  201.         DisposeHandle((Handle) helperPref);
  202.     
  203.     return err;
  204. }
  205.  
  206. void InitExternalEditor()
  207. {
  208.     FindHelper("\pHelper•editor", &gExternalEditor, false);
  209. }
  210.  
  211. void CloseExternalEditor()
  212. {
  213. }
  214.  
  215. Boolean HasExternalEdits()
  216. {
  217.     return gExternalFileCount != 0;
  218. }
  219.  
  220. void GetExternalEditorName(StringPtr name)
  221. {
  222.     char * trunc;
  223.     
  224.     if (gExternalEditor) {
  225.         HLock((Handle) gExternalEditor);
  226.         memcpy(name, gExternalEditor[0]->name, *gExternalEditor[0]->name+1);
  227.         while (trunc = (char *) memchr((char *) name+1, ' ', *name))
  228.             if (trunc == (char *) name + 1)
  229.                 memmove(name + 2, name + 1, --*name);
  230.             else
  231.                 *name = trunc - (char *)name - 1;
  232.         HUnlock((Handle) gExternalEditor);
  233.     } else
  234.         strcpy((char *) name, (char *) "\pEditor");
  235. }
  236.  
  237. static OSErr FindExternalDocument(
  238.     Boolean front, FSSpec * spec, short * index, short *fileIndex)
  239. {
  240.     OSErr                        err;
  241.     short                        i;
  242.     short                        file;
  243.     ProcessSerialNumber    psn;
  244.     AppleEvent                getEvent;
  245.     AppleEvent                getReply;
  246.     DescType                    type;
  247.     Size                        size;
  248.     char *                    title;
  249.     char                        name[260];
  250.     
  251.     if (!gExternalFileCount)    /* No external edits currently known */
  252.         return fnfErr;
  253.  
  254.     FAILOSERR(EditorRunning(gExternalEditor[0]->fCreator, &psn));
  255.  
  256.     for (i=1;; ++i) {    
  257.         FAILOSERR(
  258.             AEBuildAppleEvent(
  259.                 kAECoreSuite, kAEGetData,
  260.                 typeProcessSerialNumber, &psn, sizeof(psn), 0, 0, 
  261.                 &getEvent,
  262.                 "'----':"
  263.                     "obj{"
  264.                         "want:type('prop'),"
  265.                         "from:obj{"
  266.                             "want:type('cwin'),"
  267.                             "from:(),"
  268.                             "form:'indx',"
  269.                             "seld:long(@)"
  270.                         "},"
  271.                         "form:'prop',"
  272.                         "seld:type('pnam')"
  273.                     "}",
  274.                 i));
  275.         err = 
  276.             AESend(
  277.                 &getEvent, &getReply, 
  278.                 kAEWaitReply+kAENeverInteract, kAENormalPriority, kAEDefaultTimeout,
  279.                 &uSubLaunchIdle, nil);
  280.         AEDisposeDesc(&getEvent);
  281.         if (err)
  282.             return err;
  283.         err = AEGetKeyPtr(&getReply, '----', 'TEXT', &type, name, 260, &size);
  284.         AEDisposeDesc(&getReply);
  285.         if (err)
  286.             return err;
  287.         name[size] = 0;
  288.         if (title = strrchr(name, ':'))
  289.             ++title;
  290.         else
  291.             title = name;
  292.         if (front) {
  293.             HLock((Handle) gExternalFiles);
  294.             for (file = 0; file<gExternalFileCount; ++file) {
  295.                 FSSpec * thisFile = gExternalFiles[0]+(file<<1)+1;
  296.                 if (!memcmp(thisFile->name+1, title, *thisFile->name))
  297.                     break;
  298.             }
  299.             HUnlock((Handle) gExternalFiles);
  300.             if (file<gExternalFileCount) {
  301.                 if (spec)
  302.                     *spec = gExternalFiles[0][file<<1];
  303.                 if (index)
  304.                     *index= i;
  305.                 if (fileIndex)
  306.                     *fileIndex = file;
  307.                 
  308.                 return noErr;
  309.             } else
  310.                 return fnfErr;
  311.         } else {
  312.             if (!memcmp(spec->name+1, title, *spec->name)) {
  313.                 if (index)
  314.                     *index= i;
  315.                 return noErr;
  316.             }
  317.         }
  318.     }
  319. }
  320.  
  321. Boolean GetExternalEditorDocumentName(StringPtr name)
  322. {
  323.     OSErr            err;
  324.     short         index;
  325.     FSSpec        spec;
  326.     
  327.     if (err = FindExternalDocument(true, &spec, nil, &index))
  328.         return false;
  329.         
  330.     memcpy(name, spec.name, *spec.name+1);
  331.     
  332.     return true;
  333. }
  334.  
  335. static OSErr SendEditorEvent(OSType eventID, FSSpec * file)
  336. {
  337.     OSErr                        err;
  338.     ProcessSerialNumber     psn;
  339.     AppleEvent                editorEvent;
  340.     AppleEvent                ignoreReply;
  341.  
  342.     MakeSelfPSN(&psn);
  343.             
  344.     FAILOSERR(
  345.         AEBuildAppleEvent(MPAppSig, eventID,
  346.                     typeProcessSerialNumber, &psn, sizeof(ProcessSerialNumber),
  347.                     0, 0, &editorEvent,
  348.                     "'----':fss(@)",
  349.                     sizeof(FSSpec), file));
  350.     err =    AESend(
  351.                 &editorEvent, &ignoreReply, 
  352.                 kAENoReply+kAENeverInteract, kAENormalPriority, kAEDefaultTimeout,
  353.                 nil, nil);
  354.     AEDisposeDesc(&editorEvent);
  355.     
  356.     return err;
  357. }
  358.  
  359. OSErr StartExternalEditor(Boolean front)
  360. {
  361.     OSErr    fileErr;
  362.     
  363.     if (front) {
  364.         WindowPtr    win;
  365.         DPtr            doc;
  366.         
  367.         for (win = FrontWindow(); win; win = GetNextWindow(win)) {
  368.             if (!IsWindowVisible(win) || !Ours(win))
  369.                 continue;
  370.             if ((doc = DPtrFromWindowPtr(win)) && doc->kind == kDocumentWindow)
  371.                 break;
  372.         }
  373.         
  374.         if (!win)
  375.             return fnfErr;
  376.  
  377.         if (doc->dirty || !doc->u.reg.everSaved) {
  378.             if (!doc->u.reg.everSaved) {
  379.                 fileErr = GetFileNameToSaveAs(doc);
  380.                 if (!fileErr)
  381.                     fileErr = IssueSaveCommand(doc, &doc->theFSSpec);
  382.                 else if (fileErr != userCanceledErr)    
  383.                     FileError((StringPtr) "\perror saving ", doc->theFileName);
  384.             } else
  385.                 fileErr = IssueSaveCommand(doc, nil);
  386.             if (fileErr)
  387.                 return fileErr;
  388.         }
  389.  
  390.         return SendEditorEvent('xEDT', &doc->theFSSpec);
  391.     } else {
  392.         StandardFileReply    reply;
  393.         
  394.         StandardGetFile(&uGetScriptFilter, MacPerlFileTypeCount, MacPerlFileTypes, &reply);
  395.         if (reply.sfGood)
  396.             return SendEditorEvent('xEDT', &reply.sfFile);
  397.         else 
  398.             return userCanceledErr;
  399.     }
  400. }
  401.  
  402. OSErr EditExternal(FSSpec * spec)
  403. {
  404.     return SendEditorEvent('xEDT', spec);
  405. }
  406.  
  407. /* Defined in MacPerl.xs */
  408. #if USESROUTINEDESCRIPTORS
  409. extern RoutineDescriptor    uMacListUpdate;
  410. extern RoutineDescriptor    uMacListFilter;
  411. #else
  412. pascal void MacListUpdate();
  413. pascal void MacListFilter();
  414. #define uMacListUpdate MacListUpdate
  415. #define uMacListFilter MacListFilter
  416. #endif
  417. extern ListHandle    gPickList;
  418.  
  419. static void UpdateList()
  420. {
  421.     short            itemHit;
  422.     Boolean        done;
  423.     DialogPtr    dlg;
  424.     Cell            mycell;
  425.     short            mytype;
  426.     Handle        myhandle;
  427.     Point            cellsize;
  428.     Rect            listrect, dbounds;
  429.         
  430.     InitCursor();
  431.     dlg = GetNewDialog(2020, NULL, (WindowPtr)-1);
  432.     
  433.     SetText(dlg, 3, "\pSelect the files to update:");
  434.     GetDItem(dlg, 4, &mytype, &myhandle, &listrect);
  435.     SetDItem(dlg, 4, mytype, (Handle)&uMacListUpdate, &listrect);
  436.     
  437.     SetPort(dlg);
  438.     InsetRect(&listrect, 1, 1);
  439.     SetRect(&dbounds, 0, 0, 1, gExternalFileCount);
  440.     cellsize.h = (listrect.right - listrect.left);
  441.     cellsize.v = 17;
  442.  
  443.     listrect.right -= 15;
  444.  
  445.     gPickList = LNew(&listrect, &dbounds, cellsize, 0,
  446.                             dlg, true, false, false, true);
  447.  
  448.     LDoDraw(false, gPickList);
  449.     
  450.     HLock((Handle) gExternalFiles);
  451.     mycell.h = mycell.v = 0;
  452.     for (; mycell.v<gExternalFileCount; ++mycell.v)    {
  453.         StringPtr    name = gExternalFiles[0][mycell.v].name;
  454.         LSetCell(name+1, *name, mycell, gPickList);
  455.     }
  456.     HUnlock((Handle) gExternalFiles);
  457.  
  458.     LDoDraw(true, gPickList);
  459.     ShowWindow(dlg);
  460.     
  461.     for (done=false; !done; ) {
  462.         SetPort(dlg);
  463.         DrawDefaultOutline(dlg, ok);
  464.         ModalDialog((ModalFilterUPP) &uMacListFilter, &itemHit);
  465.         switch (itemHit) {
  466.         case ok:
  467.             mycell.h = mycell.v = 0;
  468.             done = true;
  469.             HLock((Handle) gExternalFiles);
  470.             while (LGetSelect(true, &mycell, gPickList)) {
  471.                 SendEditorEvent('xUPD', gExternalFiles[0]+(mycell.v << 1));
  472.                 LDelRow(1, mycell.v, gPickList);
  473.             }
  474.             if (gExternalFiles)
  475.                 HUnlock((Handle) gExternalFiles);
  476.             break;
  477.         case cancel:
  478.             done = true;
  479.             break;
  480.         }
  481.     }    /* Modal Loop */
  482.  
  483.     SetPort(dlg);
  484.     
  485.     LDispose(gPickList);
  486.     gPickList = nil;
  487.     DisposDialog(dlg);
  488. }
  489.  
  490. OSErr UpdateExternalEditor(Boolean front)
  491. {
  492.     if (front) {
  493.         OSErr            err;
  494.         FSSpec        spec;
  495.         
  496.         FAILOSERR(FindExternalDocument(true, &spec, nil, nil));
  497.         
  498.         return SendEditorEvent('xUPD', &spec);
  499.     } else {
  500.         UpdateList();
  501.         
  502.         return noErr;
  503.     }
  504. }
  505.  
  506. static OSErr MakeScratch(FSSpec * file, FSSpec * scratch)
  507. {
  508.     OSErr            err;
  509.     DocType        docType;
  510.     CInfoPBRec    info;
  511.     
  512.     FAILOSERR(
  513.         FindFolder(kOnSystemDisk, kTemporaryFolderType, true, 
  514.             &scratch->vRefNum, &scratch->parID));
  515.     memcpy(scratch->name, file->name, *file->name+1);
  516.     if (*scratch->name > 24)
  517.         return bdNamErr;
  518.     memcpy(scratch->name+*scratch->name+1, " [Perl]", 7);
  519.     *scratch->name += 7;
  520.     if (!FSpCatInfo(scratch, &info)) {
  521.         if (*scratch->name > 28)
  522.             return bdNamErr;
  523.         memcpy(scratch->name+*scratch->name+1, " #1", 3);
  524.         *scratch->name += 3;
  525.         do {
  526.             ++scratch->name[*scratch->name];
  527.         } while (!FSpCatInfo(scratch, &info));
  528.     }
  529.     docType = GetDocType(file);
  530.             
  531.     if (docType == kUnknownDoc)
  532.         return errAEWrongDataType;
  533.     else
  534.         return File2File(*file, docType, *scratch, 'TEXT');
  535.  
  536.     return noErr;
  537. }
  538.  
  539. pascal OSErr DoExternalEditor(const AppleEvent * event, AppleEvent * reply, long refCon)
  540. {
  541.     OSErr                        err;
  542.     char                        state;
  543.     int                        i;
  544.     DescType                    type;
  545.     Size                        size;
  546.     WindowPtr                win;
  547.     FSSpec                    file;
  548.     FSSpec                    scratch;
  549.     ProcessSerialNumber    psn;
  550.     
  551.     FAILOSERR(
  552.         AEGetParamPtr(event, '----', 
  553.             typeFSS, &type, (Ptr)&file, sizeof(FSSpec), &size));
  554.  
  555.     if (!gExternalFileCount)
  556.         i = 0;
  557.     else {
  558.         state = HGetState((Handle) gExternalFiles);
  559.         HLock((Handle) gExternalFiles);
  560.         for (i = 0; i < (gExternalFileCount << 1); ++i)
  561.             if (SameFSSpec(gExternalFiles[0]+i, &file))
  562.                 break;
  563.         HSetState((Handle) gExternalFiles, state);
  564.     }
  565.     
  566.     i >>= 1;
  567.     
  568.     if (!refCon)    {                        /* Edit */
  569.         AppleEvent    openEvent;
  570.         AppleEvent    ignoreReply;
  571.         
  572.         if (EditorRunning(gExternalEditor[0]->fCreator, &psn)) {
  573.             FSSpec    editor;
  574.             
  575.             FAILOSERR(FindExternalEditor(gExternalEditor[0]->fCreator, &editor));
  576.             FAILOSERR(LaunchIt(&editor, &psn));
  577.         }
  578.         if (i < gExternalFileCount)
  579.             scratch = gExternalFiles[0][(i<<1)+1];
  580.         else {
  581.             FAILOSERR(MakeScratch(&file, &scratch));
  582.             if (!gExternalFileCount++)
  583.                 PtrToHand((Ptr) &file, (Handle *)&gExternalFiles, sizeof(FSSpec));
  584.             else
  585.                 PtrAndHand((Ptr) &file, (Handle)gExternalFiles, sizeof(FSSpec));
  586.             PtrAndHand((Ptr) &scratch, (Handle)gExternalFiles, sizeof(FSSpec));
  587.         }
  588.         FAILOSERR(
  589.             AEBuildAppleEvent(kCoreEventClass, kAEOpenDocuments,
  590.                         typeProcessSerialNumber, &psn, sizeof(ProcessSerialNumber),
  591.                         0, 0, &openEvent,
  592.                         "'----':fss(@),FSnd:type('McPL')",
  593.                         sizeof(FSSpec), &scratch));
  594.         err =    AESend(
  595.                     &openEvent, &ignoreReply, 
  596.                     kAENoReply+kAENeverInteract, kAENormalPriority, kAEDefaultTimeout,
  597.                     nil, nil);
  598.         AEDisposeDesc(&openEvent);
  599.         
  600.         return err;
  601.     } else {                                    /* Update */
  602.         short        windowIndex;
  603.         FSSpec *    files;
  604.         
  605.         if (i == gExternalFileCount)
  606.             return fnfErr;
  607.         files = gExternalFiles[0]+(i<<1);
  608.         HLock((Handle) gExternalFiles);
  609.         if (refCon != 2 && !FindExternalDocument(false, files, &windowIndex, nil)) {
  610.             AppleEvent                closeEvent;
  611.             AppleEvent                ignoreReply;
  612.             ProcessSerialNumber    psn;
  613.             
  614.             EditorRunning(gExternalEditor[0]->fCreator, &psn);
  615.             AEBuildAppleEvent(
  616.                 kAECoreSuite, kAEClose,
  617.                 typeProcessSerialNumber, &psn, sizeof(psn), 0, 0, 
  618.                 &closeEvent,
  619.                 "'----':"
  620.                     "obj{"
  621.                         "want:type('cwin'),"
  622.                         "from:(),"
  623.                         "form:'indx',"
  624.                         "seld:long(@)"
  625.                     "},"
  626.                 "savo:'yes '",
  627.                 windowIndex);
  628.             AESend(
  629.                     &closeEvent, &ignoreReply, 
  630.                     kAEWaitReply+kAENeverInteract, kAENormalPriority, kAEDefaultTimeout,
  631.                     nil, nil);
  632.             AEDisposeDesc(&closeEvent);
  633.         }
  634.         err = File2File(files[1], 'TEXT', files[0], GetDocType(files));
  635.         if (refCon != 2)
  636.             FSpDelete(files+1);
  637.         if (win = AlreadyOpen(files, nil)) {
  638.             CloseMyWindow(win);
  639.             OpenOld(*files, GetDocType(files));
  640.         }
  641.         HSetState((Handle) gExternalFiles, state);
  642.         if (refCon != 2) {
  643.             Munger((Handle) gExternalFiles, i*sizeof(FSSpec), nil, 2*sizeof(FSSpec), nil, 0);
  644.             if (!--gExternalFileCount) {
  645.                 DisposeHandle((Handle) gExternalFiles);
  646.                 gExternalFiles = 0;
  647.             }
  648.         }
  649.         return err;
  650.     }
  651. }
  652.